/**
 * 
 */

/**
 * @author Medrano
 *
 */
public class BinaryTree<E> implements BinaryTrees<E>{

	
	
	protected E val; // value associated with node
	protected BinaryTree<E> parent; // parent of node
	protected BinaryTree<E> left, right; // children of node
	
	/**
	 * Constructor	Permite crear un arbol binario de HuffMan en blanco
	 */
	public BinaryTree(){
		
		val = null;
		parent = null; left = right = this;
		
	}
	
	/**
	 * Constructor Permite crear un arbol binario de HuffMan asignandole un valor al nodo central
	 * @param value
	 */
	public BinaryTree(E value){
		
		val = value;
		right = left = new BinaryTree<E>();
		setLeft(left);
		setRight(right);
	}
	
	/**
	 * Constructor Permite crear un arbol vinario de Huffman indicando un valor al nodo centro, 
	 * un hijo izquierdo y un hijo derecho
	 * @param value		Valor almacenado en el nodo
	 * @param left		Referencia al hijo izquierdo
	 * @param right		Referencia al hijo derecho
	 */
	public BinaryTree(E value, BinaryTree<E> left, BinaryTree<E> right){
		val = value;
		if (left == null) { left = new BinaryTree<E>(); }
		setLeft(left);
		if (right == null) { right = new BinaryTree<E>(); }
		setRight(right);
		
	}
	
	
	/**
	 * Permite verificar si este Arbol es el hijo izquierdo de su padre
	 */
	@Override
	public boolean isLeftChild() {
		// TODO Auto-generated method stub
		if(parent == null){
			return false;
		}
		else{
			if(this.parent.left()==this){
				return true;
			}
			else{
				return false;
			}
		}
	}
	
	public boolean isRightChild(){
		if(parent == null){
			return false;
		}
		else{
			if(this.parent.right()==this){
				return true;
			}
			else{
				return false;
			}
		}
	}

	/**
	 * Devuelve una referencia al hijo izquierdo (arbol izquierdo)
	 */
	@Override
	public BinaryTree<E> left() {
		// TODO Auto-generated method stub
		return left;
	}
	
	/**
	 * Devuelve una referencia al hijo derecho (arbol derecho)
	 */
	public BinaryTree<E> right(){
		return right;
	}

	/**
	 * Devuelve una referencia al nodo padre (o null si este no existe)
	 */
	@Override
	public BinaryTree<E> parent() {
		// TODO Auto-generated method stub
		return null;
	}

	
	public boolean isEmpty(){
		return (val==null);
	}
	
	/**
	 * Permite establecer un nuevo hijo izquierdo del arbol
	 */
	@Override
	public void setLeft(BinaryTree<E> newLeft) {
		// TODO Auto-generated method stub
		if (isEmpty()) return;
		if (left != null && left.parent() == this) left.setParent(null);
		left = newLeft;
		left.setParent(this);
	}

	/**
	 * Permite establecer un nuevo padre del arbol
	 */
	@Override
	public void setParent(BinaryTree<E> newParent) {
		// TODO Auto-generated method stub
		if (!isEmpty()) {
			parent = newParent;
		}
		
	}

	/**
	 * Permite establecer un valor a este arbol
	 */
	@Override
	public void setValue(E value) {
		// TODO Auto-generated method stub
		val = value;
		
	}

	/**
	 * Permite obtener el valor de este arbol, 
	 */
	@Override
	public E value() {
		// TODO Auto-generated method stub
		return val;
	}
	
	
	public void setRight(BinaryTree<E> newRight){
		if (isEmpty()) return;
		if (right != null && right.parent() == this) right.setParent(null);
		right = newRight;
		right.setParent(this);
	}
	

}
